#ifndef __THREAD_HPP__
#define __THREAD_HPP__

#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>

namespace ThreadModule
{
    using std::function;
    using std::string;
    using func_t = function<void(string name)>;

    enum class THREADSTATUS
    {
        NEW,
        RUNNING,
        STOP
    };

    static int threadnum = 1;

    class Thread
    {
    private:
        string _name;
        pthread_t _tid;
        pid_t _pid;
        bool _isJoinAble;
        THREADSTATUS _status;
        func_t _func;

    private:
        static void *ThreadFunc(void *args)
        {
            Thread *thread = static_cast<Thread *>(args);
            thread->_func(thread->_name);
            thread->_status = THREADSTATUS::RUNNING;
            return nullptr;
        }

    public:
        Thread(func_t func)
        {
            _name = "thread-" + std::to_string(threadnum++);
            _pid = getpid();
            _isJoinAble = true;
            _status = THREADSTATUS::NEW;
            _func = func;
        }
        ~Thread() {}

        bool Start()
        {
            if (_status != THREADSTATUS::RUNNING)
            {
                int ret = pthread_create(&_tid, nullptr, ThreadFunc, this);
                if (ret != 0)
                {
                    return false;
                }
                _status = THREADSTATUS::RUNNING;
                return true;
            }
            return false;
        }

        bool Stop()
        {
            if (_status == THREADSTATUS::RUNNING)
            {
                int ret = pthread_cancel(_tid);
                if (ret != 0)
                {
                    return false;
                }
                _status = THREADSTATUS::STOP;
                return true;
            }
            return false;
        }

        bool Join()
        {
            if (_isJoinAble)
            {
                int ret = pthread_join(_tid, nullptr);
                if (ret != 0)
                {
                    return false;
                }
                _status = THREADSTATUS::STOP;
                return true;
            }
            return false;
        }

        void Detach()
        {
            _isJoinAble = false;
            pthread_detach(_tid);
        }

        bool IsJoinAble()
        {
            return _isJoinAble;
        }

        string Name()
        {
            return _name;
        }
    };
}

#endif // __THREAD_HPP__